package com.greate.community.service.master;

import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.greate.community.dao.UserMapper;
import com.greate.community.dao.admin.RBACMapper;
import com.greate.community.dao.admin.UserAdminMapper;
import com.greate.community.entity.LoginTicket;
import com.greate.community.entity.Role;
import com.greate.community.entity.User;
import com.greate.community.entity.admin_master.UserAdmin;
import com.greate.community.service.UserService;
import com.greate.community.util.CommunityUtil;
import com.greate.community.util.HostHolder;
import com.greate.community.util.RedisKeyUtil;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;

import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;


import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class UserAdminService {
    @Autowired
    UserAdminMapper userAdminMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    UserMapper userMapper;

    @Autowired
    RBACMapper rbacMapper;

    @Value("${qiniu.key.access}")
    private String accessKey;

    @Value("${qiniu.key.secret}")
    private String secretKey;

    @Value("${qiniu.bucket.header.name}")
    private String headerBucketName;

    @Value("${qiniu.bucket.header.url}")
    private String headerBucketUrl;

    /**
     * 获取用户信息
     * @return
     */
    public List<UserAdmin> queryUserInfo(){
        return userAdminMapper.selectUserAdmin();
    }

    /**
     * 注销用户
     * @param userId
     * @return
     */
    public String deleteUserById(int userId) {
        userAdminMapper.deleteUserById(userId);
        return CommunityUtil.getJSONString(200,"账户注销成功");
    }

    /**
     * 更新头像
     * @param file
     * @param userId
     * @return
     */
    @Transactional
    public String uploadHeader(MultipartFile file,Integer userId) {
        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.region2());
        UploadManager uploadManager = new UploadManager(cfg);
        //默认不指定key的情况下，以文件内容的hash值作为文件名
        String key = null;

        try {
            byte[] uploadBytes = file.getBytes();
            ByteArrayInputStream byteInputStream=new ByteArrayInputStream(uploadBytes);
            Auth auth = Auth.create(accessKey, secretKey);
            String upToken = auth.uploadToken(headerBucketName);
            try {
                Response response = uploadManager.put(byteInputStream,key,upToken,null, null);
                //解析上传成功的结果
                DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
                System.out.println(putRet.key);
                System.out.println(putRet.hash);
                if (putRet.key!=null){

                    // 文件在云服务器上的的访问路径
                    String url = "http://"+headerBucketUrl + "/" + putRet.key;
                    userService.updateHeader(userId, url);


                    return CommunityUtil.getJSONString(200,url);
                }
            } catch (QiniuException ex) {
                Response r = ex.response;
                System.err.println(r.toString());
                try {
                    System.err.println(r.bodyString());
                } catch (QiniuException ex2) {
                    //ignore
                }
            }
        } catch (UnsupportedEncodingException ex) {
            //ignore
        } catch (IOException e) {
            e.printStackTrace();
        }
        return CommunityUtil.getJSONString(500,"上传失败");
    }

    /**
     * 管理员更新用户信息
     * 这里应该是先查出来 数据没改变就不更新了
     * 我这里不想写那么麻烦 就全部更新
     * @param user
     * @return
     */
    @Transactional
    public String undateUserInfo(Map<String, String> user) {
        try{
            String userInfo = user.get("userInfo");
            String hasrole = user.get("hasrole");
            String forbid = user.get("forbid");
            //获得userAdmin信息 并更新
            UserAdmin userAdmin = JSON.parseObject(userInfo, UserAdmin.class);
            updateUserBaseInfo(userAdmin);
            //获得现有用户角色信息 并更新角色
            List<Integer> roles = JSON.parseArray(hasrole, Integer.class);
            updateUserRoleInfo(userAdmin.getId(),roles);
            //用户禁言状态  只有用户信息是1的时候 表示禁言  才开始禁言
            int forbidTime=Integer.parseInt(forbid);
            //更新用户状态
            updateUserCondition(userAdmin.getId(),Integer.parseInt(userAdmin.getConditionalId()),forbidTime);
            return CommunityUtil.getJSONString(200,"用户信息修改成功");
        }catch (Exception e){
            e.printStackTrace();
            return CommunityUtil.getJSONString(500,"用户信息修改失败");
        }

    }

    /**
     * 修改user表中的基础信息  用户名  用户邮箱 激活状态
     * @param userAdmin
     */
    @Transactional
    public void updateUserBaseInfo(UserAdmin userAdmin){
        //先判断密码是否修改
        String OldPassword=userAdminMapper.getUserPassword(userAdmin.getId());
        if (!OldPassword.equals(userAdmin.getPassword())){//密码修改过了
            //密码加密 放入useradmin
            userAdmin.setPassword(CommunityUtil.md5(userAdmin.getPassword()+userAdmin.getSalt()));;
        }

        userAdminMapper.updateUserBaseInfo(userAdmin.getId(),
                userAdmin.getPassword(),userAdmin.getUsername(),userAdmin.getEmail(),userAdmin.getStatus());
    }

    /**
     * 修改用户所对应的角色信息  user_role表
     * @param roles
     */
    @Transactional
    public void updateUserRoleInfo(int userId,List<Integer> roles){
        //先删除角色表中用户信息
        userAdminMapper.deleteUserRoles(userId);
        //在添加角色信息
        userAdminMapper.addUserRoles(userId,roles);
    }

    /**
     * 修改用户状态 当状态是1的时候 表示禁言 要去redis中设置数据
     */
    @Transactional
    public void updateUserCondition(int userId,int conditionalId,int forbid){

        //更新数据库 用户状态
        userAdminMapper.updateUserConditional(userId,conditionalId);
        //当是禁言时
        if (conditionalId==1){
            if (forbid==-1){//取消禁言
                redisTemplate.delete(RedisKeyUtil.getForbidStatus(userId+""));
            }
            System.out.println("禁言"+forbid+"小时");
            //需要处理redis
            // 需要两个字段  一个表示禁言 一个表示mysql数据库是否更新 不禁言 数据库需要更新
            redisTemplate
                    .opsForValue()
                    .set(RedisKeyUtil.getForbidStatus(userId+""),"禁言",forbid,TimeUnit.HOURS);

            //当禁言到期后 去查看该属性 若是1 则代表数据库未更新 去更新
            redisTemplate
                    .opsForValue()
                    .set(RedisKeyUtil.getMysqlForbidStatus(userId+""),1,forbid,TimeUnit.HOURS);
        }

        //注销账号
        if (conditionalId==2){
            //退出登录
            String key = (String) redisTemplate.opsForValue().get(userId+"");//类型转换异常
            if (key!=null&!StringUtils.equals(key,"")){
                LoginTicket ticket = (LoginTicket) redisTemplate.opsForValue().get(key);//获得凭证
                if (ticket!=null&&ticket.getStatus()==0&&ticket.getExpired().after(new Date())){//判断凭证是否有效
                    //用户已经登录 更新凭证状态为2（退出登录）
                    ticket.setStatus(2);
                    redisTemplate.opsForValue().set(key,ticket);

                }
            }

        }
    }

    /**
     * 添加用户
     * @param user
     * @return
     */
    @Transactional
    public String addUser(Map<String, String> user) {

        String userInfo = user.get("userInfo");
        String hasrole = user.get("hasrole");
        String forbid = user.get("forbid");
        //获得userAdmin信息 并更新
        UserAdmin userAdmin = JSON.parseObject(userInfo, UserAdmin.class);
        //获得现有用户角色信息 并更新角色
        List<Integer> roles = JSON.parseArray(hasrole, Integer.class);

        userAdmin.setSalt(CommunityUtil.generateUUID().substring(0, 5)); // salt
        userAdmin.setPassword(CommunityUtil.md5(userAdmin.getPassword() + userAdmin.getSalt())); // 加盐加密

        userAdmin.setActivationCode(CommunityUtil.generateUUID()); // 激活码
        // 随机头像（未加图像自动生成）
//        if (userAdmin.getHeaderUrl()==null&&userAdmin.getHeaderUrl().equals("")){
            userAdmin.setHeaderUrl(String.format("http://images.nowcoder.com/head/%dt.png", new Random().nextInt(1000)));

//        }
        userAdmin.setCreateTime(new Date()); // 注册时间
        userMapper.insertUser(userAdmin);//初始化用户

        //获得用户Id
        User userInfoId = userMapper.selectByName(userAdmin.getUsername());

        //添加用户状态
        userMapper.insertUserConditional(userInfoId.getId(),Integer.parseInt(userAdmin.getConditionalId()));//初始化账户状态 为正常
        //用户角色
        for (int role :roles){
            rbacMapper.addUserRole(userInfoId.getId(),role);//默认为用户赋予普通用户角色
        }
        return CommunityUtil.getJSONString(200,"用户添加成功");
    }
}
